/**
  * Author: Mei
  * Date: 2020-12-30 19:13
  * Description: 通过索引来取值
  *
  *
  */
#include "../head.h"

namespace detail {
    //对于可转换的类型则直接比较
    //is_convertible<T, U>::value || is_convertible<U, T>::value 这个为true的话  type才为bool类型  否则实例化失败  但编译不会报错
    template<typename T, typename U>
    typename enable_if<is_convertible<T, U>::value || is_convertible<U, T>::value, bool>::type
    compare(T t, U u) {
        return t == u;
    };

    //不能相互转换则直接返回false
    bool compare(...) {
        return false;
    }

    //根据值查找索引
    template<int I, typename T, typename ... Args>
    struct find_index {
        static int call(tuple<Args...> const &t, T &&val) {
            //cout << "I: "<< I << endl;
            return (compare(get<I>(t), val) ?
                   I:
                   find_index<I - 1, T, Args...>::call(t, forward<T>(val)));
        }
    };

    template<typename T, typename ... Args>
    struct find_index<0, T, Args...> {
        //递归终止，如果找到返回0，否则返回-1
        static int call(tuple<Args...> const &t, T &&val) {
            return compare(get<0>(t), val) ? 0 : -1;
        }
    };
}

//辅助函数，简化调用
template<typename T, typename ... Args>
int find_index(tuple<Args...> const &t, T &&val) {
    //cout <<"size: "<< sizeof...(Args) << endl;
    return detail::find_index<sizeof...(Args) - 1, T, Args...>::call(t, forward<T>(val));
};

int main() {
    tuple<int, short, double, char, int, bitset<8>> tp = make_tuple(1, 2, 3, 'a', 10, 29);
    cout << get<4>(tp) << endl;
    cout << find_index(tp, 22) << endl;



    return 0;
}